import unittest
import omixed
import random
import os

from omixed import OmixedAdminClient
from omixed import OmixedClient
from omixed import OmixedException
from omixed import OmixedItem
from omixed import OmixedQuery
from omixed import OmixedServerException

from connections import host,resourceName,userName,password,adminUserName,adminPassword


"""
	A basic connection test
"""

class testMakeItemID(unittest.TestCase):
	
	def testMakeIDWithType(self):
		client = OmixedClient(host)
		sessionID = client.connect(resourceName, userName, password)
		
		itemID = client.getDomainName() + "/" + resourceName + "/" + "Study"
		self.assertEquals(itemID, client.makeItemID("Study"))
		
	def testMakeIDWithOwner(self):
		client = OmixedClient(host)
		sessionID = client.connect(resourceName, userName, password)
	
		itemID = client.getDomainName() + "/" + resourceName + "/" + "Study" + "/" + "someone"
		self.assertEquals(itemID, client.makeItemID("Study", "someone"))
		
	def testMakeIDWithName(self):
		client = OmixedClient(host)
		sessionID = client.connect(resourceName, userName, password)
	
		itemID = client.getDomainName() + "/" + resourceName + "/" + "Study" + "/" + "someone" + "/" + "some study"
		self.assertEquals(itemID, client.makeItemID("Study", "someone", "some study"))


class TestExceptions(unittest.TestCase):
	def testWrongDetails(self):
		try:
			client = OmixedClient(host)
			sessionID = client.connect(resourceName, userName, password+"sss")
		except OmixedServerException, e:
			self.assertEquals('Unable to connect, incorrect user name or password', e.faultstring)
		except OmixedException, ee:
			print ee
			self.fail("Should not be an OmixedException, but an OmixedServerException")
			
	def testWrongHost(self):
			try:
				client = OmixedClient(host+"sssssssssss")
				sessionID = client.connect(resourceName, userName, password)
			except OmixedServerException, e:
				self.fail("Should not be an OmixedServerException, but an OmixedException")
			except OmixedException, ee:
				self.assertTrue(ee.value != None)
		

		

class testBasicConnection(unittest.TestCase):
	
	def testBasicConnection(self):
		
		client = OmixedClient(host)
		sessionID = client.connect(resourceName, userName, password)
		self.assertTrue(len(client.getSessionID()) == 20 )
		self.assertEquals(client.disconnect(), "OK")
	

class BaseTest(unittest.TestCase):
	def buildExperiment(self, client):
		upload_file_path = "tests/files/animal.jpeg"
		
		download_path = "tests/downloaded_files/"
		download_file_name = "animal2.jpeg"
		download_file_path = download_path+download_file_name
		
		if os.path.isfile(download_file_path):
			os.remove(download_file_path)
			self.assertFalse(os.path.isfile(download_file_path))
			
		fileID = client.upload(upload_file_path)
		
		categoryValue = "disease"
		labelValue = "funny colour"
		self.sampleitem = self.createSample(client, categoryValue, labelValue, "Serum4444")
		
		samplevalid  = client.itemValidate(self.sampleitem, False)
		samplecreated  = client.itemCreate(self.sampleitem)
		
		self.item = self.createExperimentalAssay(client, "roger", fileID, self.sampleitem.itemID, "myAssay")
		
		valid  = client.itemValidate(self.item, False)
		created  = client.itemCreate(self.item)
		
		self.assertEquals(valid, "OK")
		self.assertEquals(created, "OK")
		
		#########################################
		# NOTE NEW GENERIC ITEMFIND() INTERFACE #
		#########################################
		itemFromServer = client.itemFind(OmixedQuery.FULL_ITEM_DETAILS, "<ItemID>" + self.item.itemID + "</ItemID>" )[0]
		itemFromServerXML = itemFromServer.getXML()
		
		client.download(fileID, download_path, download_file_name)
		self.assertTrue(os.path.isfile(download_file_path))
		self.assertEquals( os.path.getsize(upload_file_path), os.path.getsize(download_file_path) )
	
	def destroyExperiment(self, client):
		#########################################
		# NOTE NEW GENERIC LOCKACQUIRE() METHOD #
		#########################################
		client.lockAcquire(self.item.itemID)
		deleted  = client.itemDelete(self.item.itemID)
		self.assertEquals(deleted, "OK")
		
		client.lockAcquire(self.sampleitem.itemID)
		sampledeleted  = client.itemDelete(self.sampleitem.itemID)
		self.assertEquals(sampledeleted, "OK")
		
		


	def createExperimentalAssay(self, client, userValue, fileID, sampleID, name):
		item = OmixedItem()
		item.setupNewItem(client, "Assay", name, "public")
		item.setAttribute ("User", userValue)
		item.setFileID ("grams data file", fileID)
		item.setLink ("assayed sample", sampleID)
		return item

	def createSample(self, client, categoryValue, labelValue, name):
		item = OmixedItem()
		item.setupNewItem(client, "Sample", name, "public")
		item.setAttribute ("label", labelValue)
		item.setAttribute ("category class", categoryValue)
		return item



"""
  All tests here designed to work on raman schema.
"""
class testClient(BaseTest):
  
  # always initialise a client before every test
	def setUp(self):
		self.client = OmixedClient(host)
		self.client.connect(resourceName, userName, password)

		self.numberOfSamples = 1
		self.categories = ["disease", "control"]
		self.labels = ["normal", "funny colour", "smelly", "dark", "solid"]
  
  # always disconnect after every test
	def tearDown(self):
		self.client.disconnect()
  
	def testConnection(self):
		self.assertNotEqual(self.client, None)
		self.assertTrue(len(self.client.getSessionID()) == 20 )
  
	def testGetItemTypes(self):
		itemTypes = self.client.schemaEnumerateItemTypes()
		self.assertTrue(len(itemTypes) > 0)

	def testItem1(self):
		item = OmixedItem()
		
		name = "newSample"
		labelValue = "red"
		categoryValue = "Serum225"
		
		item.setupNewItem(self.client, "Sample", name, "public")
		item.setAttribute ("label", labelValue)
		item.setAttribute ("category class", categoryValue)
		
		labelFromItem = item.getAttribute("label")
		categoryFromItem = item.getAttribute("category class")
		
		self.assertEquals(labelFromItem, labelValue)
		self.assertEquals(categoryFromItem, categoryValue)
		
	def testItem2(self):

		categoryValue = "disease"
		labelValue = "funny colour"

		item = self.createSample(self.client, categoryValue, labelValue, "Serum225")

		labelFromItem = item.getAttribute("label")
		categoryFromItem = item.getAttribute("category class")

		self.assertEquals(labelFromItem, labelValue)
		self.assertEquals(categoryFromItem, categoryValue)
	
	
	def testItem3(self):
		categoryValue = "disease"
		labelValue = "funny colour"
		item = self.createSample(self.client, categoryValue, labelValue, "Serum310")
		valid  = self.client.itemValidate(item, False)
		self.assertEquals(valid, "OK")

	def testOmixedItemSamplesCRUD(self):
		x = 0
		while x <= self.numberOfSamples:
			categoryValue = random.choice (self.categories)
			labelValue = random.choice (self.labels)
			
			name = "SerumAlpha_"+categoryValue + str(x)
			
			item = self.createSample(self.client, categoryValue, labelValue, name)
			
			valid  = self.client.itemValidate(item, False)
			created  = self.client.itemCreate(item)
			
			#########################################
			# NOTE NEW GENERIC LOCKACQUIRE() METHOD #
			#########################################
			
			locked = self.client.lockAcquire(item.itemID)
			deleted  = self.client.itemDelete(item.itemID)
			
			self.assertEquals(valid, "OK")
			self.assertEquals(created, "OK")
			self.assertEquals(deleted, "OK")
			
			x = x + 1


	def testGetItems(self):
		itemTypes = self.client.schemaEnumerateItemTypes()
		for itemType in itemTypes:
			#########################################
			# NOTE NEW GENERIC ITEMFIND() INTERFACE #
			#########################################
			itemIDs = self.client.itemFind("ITEM_ID", "<ItemType>Sample</ItemType>")
		
	def testSampleCreateAndBrowse(self):
		x = 0

		labelValues = []
		categoryValues = []
		sampleItems = []
		sampleItemIDs = []
		while x <= self.numberOfSamples:
			categoryValue = random.choice (self.categories)
			labelValue = random.choice (self.labels)
			categoryValues.append(categoryValue)
			labelValues.append(labelValue)
			name = "SerumBeta_"+categoryValue + str(x)
			sampleItem = OmixedItem()
			sampleItem.setupNewItem(self.client, "Sample", name, "public")
			sampleItem.testString = name + "_" + str(x)
			sampleItem.setAttribute ("label", labelValue)
			sampleItem.setAttribute ("category class", categoryValue)
			sampleItems.append(sampleItem)
			sampleItemIDs.append(sampleItem.itemID)
			x = x + 1
		
		do_create = True
		do_browse = True
		do_delete = True
		
		if do_create:
			for sample_to_create in sampleItems:
				valid  = self.client.itemValidate(sample_to_create, False)
				self.assertEquals(valid, "OK")
				created  = self.client.itemCreate(sample_to_create)
				self.assertEquals(created, "OK")
		
		if do_browse:
			#########################################
			# NOTE NEW GENERIC ITEMFIND() INTERFACE #
			#########################################
			itemIDs = self.client.itemFind(OmixedQuery.ITEM_ID, "<ItemType>Sample</ItemType>")
			for itemID in itemIDs:
				self.assertTrue(itemID in sampleItemIDs)
			
			itemsFromServer = self.client.itemFind(OmixedQuery.FULL_ITEM_DETAILS, "<ItemType>Sample</ItemType>")
			for item in itemsFromServer:
				self.assertTrue(item.itemID in sampleItemIDs)
		
		if do_delete:
			# reverse actually reverses the array rather than return a new one
			sampleItems.reverse()
			
			for sample_to_delete in sampleItems:
				try:
					#########################################
					# NOTE NEW GENERIC LOCKACQUIRE() METHOD #
					#########################################
					locked  = self.client.lockAcquire(sample_to_delete.itemID)
					deleted  = self.client.itemDelete(sample_to_delete.itemID)
					self.assertEquals(deleted, "OK")
				except OmixedServerException, e:
					print e

  
	def testBuildExperiment(self):
		self.buildExperiment(self.client)
		self.destroyExperiment(self.client)
	
	



class TestAdminClient(BaseTest):
	
	resourceNamePrefix = "pythontest01"
	
	def test1(self):
		adminClient = OmixedAdminClient(host, adminUserName, adminPassword)
		description = adminClient.serverDescribe()
		self.assertEquals("OK", description[0])
		self.assertEquals("API-Version: 2.0", description[1])


	def test2(self):
			adminClient = OmixedAdminClient(host, adminUserName, adminPassword)
			resourceName = self.resourceNamePrefix+"t2"
			
			created = adminClient.resourceCreate(resourceName)
			self.assertEquals("OK", created)
			
			resourceXML = open("tests/raman_update.xml").read()
			schemaed = adminClient.resourceSetSchema(resourceName, resourceXML)
			self.assertEquals("OK", schemaed)
			
			deleted = adminClient.resourceDelete(resourceName)
			self.assertEquals("OK", deleted)
		
		
		
	def test3(self):
		adminClient = OmixedAdminClient(host, adminUserName, adminPassword)
		resourceName = self.resourceNamePrefix+"t3"
		resourceFileName = "backup"
		
		created = adminClient.resourceCreate(resourceName)
		self.assertEquals("OK", created)
		
		resourceXML = open("tests/raman_update.xml").read()
		schemaed = adminClient.resourceSetSchema(resourceName, resourceXML)
		self.assertEquals("OK", schemaed)
		
		try:
			adminClient.userCreate(userName, password, "user")
		except OmixedServerException, ose:
			print "\n" + ose.faultstring + "\n"
		
		try:
			adminClient.policyAddOnResource("allow", "connect", userName, resourceName)
		except OmixedServerException, ose2:
			print "\n" + ose2.faultstring + "\n"
		
		
		
		client = OmixedClient(host)
		client.connect(resourceName, userName, password)
		
		label = "interesting"
		
		sampleitem = self.createSample(client, "red", label, "my super sample")
		client.itemCreate(sampleitem)
		
		# make a note of the item id
		sampleitemID = sampleitem.itemID
		
		# make sure you close the session before trying a backup
		client.disconnect()
		
		backedUp = adminClient.resourceBackup(resourceName, resourceFileName)
		self.assertEquals("OK",backedUp)
		
		emptied = adminClient.resourceEmpty(resourceName)
		self.assertEquals("OK",emptied)
		
		restored = adminClient.resourceRestore(resourceName, resourceFileName)
		self.assertEquals("OK",restored)
		
		# make a new connection to the resource
		client2 = OmixedClient(host)
		client2.connect(resourceName, userName, password)
		
		# retrieve the restored itemID
		restoredItemID = client2.itemFind(OmixedQuery.ITEM_ID, "<ItemID>"+sampleitemID+"</ItemID>")[0]
		self.assertEquals(sampleitemID, restoredItemID)
		
		# retrieve the restored item and compare its label with the original
		restoredItem = client2.itemFind(OmixedQuery.FULL_ITEM_DETAILS, "<ItemID>"+sampleitemID+"</ItemID>")[0]
		self.assertEquals(label, restoredItem.getAttribute("label"))
		
		# disconnect before delete
		client2.disconnect()
		
		deleted = adminClient.resourceDelete(resourceName)
		self.assertEquals("OK", deleted)
		
		




# the magic to run the unit tests
if __name__ == "__main__":
    unittest.main()